import { debounce, merge, throttle, useAxiosPlugin } from 'axios-plugins';
import axios, { AxiosInstance, CreateAxiosDefaults } from 'axios';
import { HttpCodeEnum, MethodEnum } from '/@/utils/request/enum/MethodEnum';
import { HttpConfig, HttpResult, ParamModel, Result } from '/@/utils/request/type/AxiosModel';
import tools from '/@/utils/tools';
import { router } from '/@/router';
import { MessagePlugin } from 'tdesign-vue-next';

export class Axios {
  private readonly axiosInstance: AxiosInstance;
  private readonly options: CreateAxiosDefaults;
  constructor(options: CreateAxiosDefaults) {
    this.options = options;
    this.axiosInstance = axios.create(options);
    const plugin = useAxiosPlugin(this.axiosInstance);
    //请求合并
    plugin.plugin(merge());
    //防抖插件
    plugin.plugin(debounce());
    //节流插件
    plugin.plugin(throttle());
  }

  /**
   * ajax请求
   * @param url
   * @param method
   * @param data
   * @param config
   */
  public httpRequest(url: string, method: MethodEnum, data: object, config?: HttpConfig): Promise<any> {
    const { callBack, isHint } = tools.defaultsDeep(
      {
        callBack: () => {
          //默认函数
        },
        isHint: true,
        isToken: true,
        ...config,
      },
      config,
    );
    // const tokenStr = store.get('token');
    // //token获取
    const token = config?.isToken ? '' : '';
    const params = this.parameterTransition(method, data);
    url = this.urlDispose(url);
    return new Promise((resolve: (result) => void, reject: (err) => void) => {
      this.axiosInstance
        .request({
          url: url,
          method: method,
          ...params,
          headers: {
            Authorization: token,
          },
        })
        .then((res: HttpResult) => {
          this.resultDispose(res, resolve, reject, callBack, isHint);
        })
        .catch((err) => {
          console.error(err);
          MessagePlugin.error('系统异常,请联系管理员');
          callBack(err);
          reject(err);
        });
    });
  }

  /**
   * 请求参数转换
   * @private
   */
  private parameterTransition(method: MethodEnum, data: object): ParamModel {
    let params: ParamModel = {
      data: data,
    };
    if (method === MethodEnum.GET) {
      params = {
        params: data,
      };
    }
    return params;
  }
  /**
   * url处理
   * @param url
   * @private
   */
  private urlDispose(url: string): string {
    return import.meta.env.VITE_HTTP_PREFIX + url;
  }

  /**
   * http结果返回
   * @param res
   * @private
   */
  private resultDispose(
    res: HttpResult,
    resolve: (result) => void,
    reject: (err) => void,
    callBack: (result: Result) => void,
    isHint: boolean,
  ) {
    //回调函数
    callBack(res.data);
    switch (res.data.code) {
      case HttpCodeEnum.SUCCESS:
        if (res.data.msg) {
          //成功
          isHint ? MessagePlugin.success(res.data.msg) : '';
        }
        resolve(res.data.data);
        return;
      case HttpCodeEnum.ERROR:
        //错误
        isHint ? MessagePlugin.error(res.data.msg!) : '';
        reject(res);
        return;
      case HttpCodeEnum.WARNING:
        isHint ? MessagePlugin.warning(res.data.msg!) : '';
        reject(res.data.data);
        return;
      case HttpCodeEnum.NOT_LOGIN:
        isHint ? MessagePlugin.error(res.data.msg!) : '';
        router.push({
          name: 'login',
        });
        return;
      default:
        reject(res);
    }
  }
}
